package YAPserver;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.SocketException;

import YAPenvironment.YAPconstant;
import YAPserver.logic.Input.MoveCommand;

/**
 * UDP-socket which answers to UDP requests, as the discovery of this server
 * or the key-inputs from clients.
 */
public class DiscoveryServer extends Thread {

	private static MulticastSocket MS_in;
	private static DatagramPacket DP_out;
	
	/**
	 * This object regulates the incoming traffic of the UDPsocket: <p>
	 * -Discovery <p>
	 * -KeyInputs (left or right-arrow)
	 */
	public DiscoveryServer(){
		try{
			MS_in = new MulticastSocket(YAPconstant.C_MULTICASTPORT1);
			MS_in.joinGroup(InetAddress.getByName(YAPconstant.C_MULTICASTGROUP));
			
			byte[] data = (YAPserver.C_PORT+"").getBytes();
			DP_out = new DatagramPacket(data,data.length, InetAddress.getByName(YAPconstant.C_MULTICASTGROUP), YAPconstant.C_MULTICASTPORT2 );
			MS_in.send( DP_out );
			
			System.out.println("Server name: "+InetAddress.getLocalHost());
			this.start();
		}catch (IOException e){
			System.out.println("Couldn't initialise UDP-Socket");
			System.out.println("Server is shutting down");
			System.exit(0);
		}
		
	}
	/**
	 * Closes the multicastSocket.
	 */
	static public void close(){
		try{
			MS_in.close();
		}catch (Exception e){
			if(YAPconstant.C_DEBUG){ e.printStackTrace(); }
		}
	}
	/**
	 * Receives the incomming datagram packets and answers to them.
	 */
	public void run() {
		System.out.println("Discovery function started");
		while(YAPserver.started){
			try{
				getPackage();
			}catch (SocketException e){
				if(!YAPserver.started);
					break;
			}catch (Exception e){
				if(YAPconstant.C_DEBUG){ e.printStackTrace(); }
			}
		}
	}

	/**
	 * Reads the datagram packet.
	 * Parses it if it is an arrowCommand
	 * or sends it back to the server's ip and port for the client to connect to.
	 * @throws Exception
	 */
	private void getPackage() throws Exception{
		byte buf[] = new byte[100];
		DatagramPacket pack = new DatagramPacket(buf, buf.length);
			MS_in.receive(pack);
			String msg = new String(pack.getData());
			
			if(msg.startsWith(YAPconstant.Command.sendKey+"")){
				sendKey(pack, msg);
				return;
			}
			else if(msg.startsWith(YAPconstant.Command.noMove+"")){
				sendNoMove(pack, msg);
				return;
			}
			
			byte[] data = (YAPserver.C_PORT+"").getBytes();
			DP_out = new DatagramPacket(
					data, data.length,
					pack.getAddress(), YAPconstant.C_MULTICASTPORT2
					);
			
			
			MS_in.send(DP_out);
			System.out.println("Discovery: Answer given to: "+DP_out.getSocketAddress());
	}
	
	/**
	 * Sets the direction of the this client's slider in the game.
	 * @param pack
	 * @param strMsg String which is parsed as "left" or "right"
	 */
	public void sendKey(DatagramPacket pack, String msg){
		String[] info = msg.split(YAPconstant.C_SEPARATOR);
		if(info.length != 5)
			return;
		/*
			String direction = msg.split(YAPconstant.C_SEPARATOR)[1];
			String lobby = msg.split(YAPconstant.C_SEPARATOR)[2];
			String name  = msg.split(YAPconstant.C_SEPARATOR)[3];
		*/
		Lobby lby = YAPserver.lobbyList.get(info[2]);

		if(lby!=null && lby.isStarted()){
			for(ClientHandler cH: lby.getPlayers()){
					if(cH.getName().equals(info[3]) && pack.getAddress().equals(cH.getInetAddress())){
						cH.sendKey(info[1]);
						break;
					}
			}
		}
	}
	/**
	 * Sets the noMove command which means the client's slider will not move.
	 * @param pack
	 * @param msg
	 */
	private void sendNoMove (DatagramPacket pack, String msg){
		String[] info = msg.split(YAPconstant.C_SEPARATOR);
		if(info.length != 4)
			return;
		/*
			String lobby = msg.split(YAPconstant.C_SEPARATOR)[1];
			String name  = msg.split(YAPconstant.C_SEPARATOR)[2];
		*/
		Lobby lby = YAPserver.lobbyList.get(info[1]);
		
		if(lby!=null && lby.isStarted()){
			for(ClientHandler cH: lby.getPlayers()){
				if(cH.getName().equals(info[2]) && pack.getAddress().equals(cH.getInetAddress())){
					lby.getGame().setCommand(cH.getGameId(), MoveCommand.NOMOVE);
					break;
				}
			}
		}
	}
}
